/**
 * @file:          Config_Controller.c
 * @brief:
 * @details:
 * @author:        wjh
 * @date created:  2023.06.14
 * @version:       1.0.0
 * @par copyright (c):
 *
 * @par history (desc):
 *   version:1.0.0, wjh, 2023.06.14,00:32:09
 */

/* Include Files **************************************************************/
#include "ConfigOption.h"
#include "STRING.H"

/* Global Variable Define *****************************************************/
void Config_controller_default(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_default = {.ConfigParam = Config_controller_default};
void Config_controller_default(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_default;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14.0e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 2.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 1;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.2;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.08;
    self->id_loop_pid.param_ki = 15.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.0;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 20;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 20.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 0.5;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 1;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 0.25;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 1;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = 1;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdRef;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.65e-3;
    // self->fwc.param_phi_e = 0.121125 / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1;
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2;

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 80;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 1500;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = 1;
    self->td.param_mode = TDMode_Fhan;
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F;

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF019Pro_XY(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF019Pro_XY = {.ConfigParam = Config_controller_PF019Pro_XY};
/* X or Y axis */
void Config_controller_PF019Pro_XY(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF019Pro_XY;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14.0e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.8;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 1;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdRef;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF019Pro_Z(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF019Pro_Z = {.ConfigParam = Config_controller_PF019Pro_Z};
/* X or Y axis */
void Config_controller_PF019Pro_Z(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF019Pro_Z;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 3.0;
    self->spd_loop_pid.parma_limit_out = 3.0;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 3.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.6;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF019Pro_E(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF019Pro_E = {.ConfigParam = Config_controller_PF019Pro_E};
/* X or Y axis */
void Config_controller_PF019Pro_E(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF019Pro_E;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14.0e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 2.0;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 200.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 2.0;
    self->spd_loop_pid.parma_limit_out = 2.0;
    self->spd_loop_pid.param_kp = 0.10;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.2;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 0;
    self->spd_loop_pid.fal.param_a = 0.9;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 2.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 1.0;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 1;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 40.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 1.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 0.5;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 1;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 0.25;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 1;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = 0;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdRef;
    self->fwc.param_I_max = 2.5;
    // self->fwc.param_L = 1.2e-3;
    // self->fwc.param_phi_e = 0.0463 / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1;
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2;

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 80;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 1500;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = 1;
    self->td.param_mode = TDMode_Fhan;
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F;

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF008Pro_XY(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF008Pro_XY = {.ConfigParam = Config_controller_PF008Pro_XY};
/* X or Y axis */
void Config_controller_PF008Pro_XY(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF008Pro_XY;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.028;
    self->spd_loop_pid.param_ki = 6;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.5;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = FALSE;
    self->spd_loop_pid.fal.param_a = 1.0;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 2.5 / 3.0;
    self->id_loop_pid.param_ki = 200.0 / 3.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.5;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = FALSE;
    self->id_loop_pid.fal.param_a = 1.3;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 120;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = FALSE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 6000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = FALSE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF008Pro_Z(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF008Pro_Z = {.ConfigParam = Config_controller_PF008Pro_Z};
/* X or Y axis */
void Config_controller_PF008Pro_Z(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF008Pro_Z;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 200.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.035;
    self->spd_loop_pid.param_ki = 20;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.5;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = FALSE;
    self->spd_loop_pid.fal.param_a = 0.7;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 2.5;
    self->id_loop_pid.param_ki = 100.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.5;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = FALSE;
    self->id_loop_pid.fal.param_a = 1.3;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = FALSE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 6000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = FALSE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF008Pro_Z_LeadScrewMotor(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF008Pro_Z_LeadScrewMotor = {.ConfigParam = Config_controller_PF008Pro_Z_LeadScrewMotor};
/* X or Y axis */
void Config_controller_PF008Pro_Z_LeadScrewMotor(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF008Pro_Z_LeadScrewMotor;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 200.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 3.0;
    self->spd_loop_pid.parma_limit_out = 3.0;
    self->spd_loop_pid.param_kp = 0.08;
    self->spd_loop_pid.param_ki = 15.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 3.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.8;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdRef;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.95e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF008Pro_E(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF008Pro_E = {.ConfigParam = Config_controller_PF008Pro_E};
/* X or Y axis */
void Config_controller_PF008Pro_E(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF008Pro_E;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 2.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 1000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 150.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 1000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 2.6;
    self->spd_loop_pid.parma_limit_out = 2.6;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 35.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 2.6F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.6;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = FALSE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 2.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.0463F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 6000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_Ender3V3KE_X(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_Ender3V3KE_X = {.ConfigParam = Config_controller_Ender3V3KE_X};
/* X or Y axis */
void Config_controller_Ender3V3KE_X(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_Ender3V3KE_X;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.05;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 1.0;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.65e-3;
    // self->fwc.param_phi_e = 0.121125F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = FALSE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_Ender3V3KE_Y(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_Ender3V3KE_Y = {.ConfigParam = Config_controller_Ender3V3KE_Y};
/* X or Y axis */
void Config_controller_Ender3V3KE_Y(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_Ender3V3KE_Y;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 150.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.12;
    self->spd_loop_pid.param_ki = 4.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = TRUE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 2.0;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 1;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.65e-3;
    // self->fwc.param_phi_e = 0.121125 / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = FALSE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_Ender3V3KE_Z(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_Ender3V3KE_Z = {.ConfigParam = Config_controller_Ender3V3KE_Z};
/* X or Y axis */
void Config_controller_Ender3V3KE_Z(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_Ender3V3KE_Z;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 3.0;
    self->spd_loop_pid.parma_limit_out = 3.0;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 3.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.6;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_Ender3V3KE_E(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_Ender3V3KE_E = {.ConfigParam = Config_controller_Ender3V3KE_E};
/* X or Y axis */
void Config_controller_Ender3V3KE_E(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_Ender3V3KE_E;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 3.0;
    self->spd_loop_pid.parma_limit_out = 3.0;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 3.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.6;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_K1Max_XY(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_K1Max_XY = {.ConfigParam = Config_controller_K1Max_XY};
/* X or Y axis */
void Config_controller_K1Max_XY(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_K1Max_XY;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 3.0;
    self->spd_loop_pid.parma_limit_out = 3.0;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 3.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.8;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_K1Max_Z(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_K1Max_Z = {.ConfigParam = Config_controller_K1Max_Z};
/* X or Y axis */
void Config_controller_K1Max_Z(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_K1Max_Z;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 200.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 3.0;
    self->spd_loop_pid.parma_limit_out = 3.0;
    self->spd_loop_pid.param_kp = 0.05;
    self->spd_loop_pid.param_ki = 20.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 3.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.6;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 3.5;
    // self->fwc.param_L = 4.6e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_K1Max_E(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_K1Max_E = {.ConfigParam = Config_controller_K1Max_E};
/* X or Y axis */
void Config_controller_K1Max_E(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_K1Max_E;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 3.0;
    self->spd_loop_pid.parma_limit_out = 3.0;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 3.0F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.6;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 0;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF018_X(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF018_X = {.ConfigParam = Config_controller_PF018_X};
/* X or Y axis */
void Config_controller_PF018_X(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF018_X;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.035;
    self->spd_loop_pid.param_ki = 15;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.5;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = FALSE;
    self->spd_loop_pid.fal.param_a = 0.7;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 2.5;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.5;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = FALSE;
    self->id_loop_pid.fal.param_a = 1.3;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = FALSE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 6000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = FALSE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF018_Y(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF018_Y = {.ConfigParam = Config_controller_PF018_Y};
/* X or Y axis */
void Config_controller_PF018_Y(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF018_Y;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 200.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.02;
    self->spd_loop_pid.param_ki = 15;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.5;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = FALSE;
    self->spd_loop_pid.fal.param_a = 0.7;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 2.5;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.5;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = FALSE;
    self->id_loop_pid.fal.param_a = 1.3;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = FALSE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 6000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = FALSE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF018_Z(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF018_Z = {.ConfigParam = Config_controller_PF018_Z};
/* X or Y axis */
void Config_controller_PF018_Z(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF018_Z;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.8;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 1;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}

void Config_controller_PF018_E(ThreeLoopPidFocV1_0 *self);
ThreeLoopPidFocV1_0 controller_PF018_E = {.ConfigParam = Config_controller_PF018_E};
/* X or Y axis */
void Config_controller_PF018_E(ThreeLoopPidFocV1_0 *self)
{
    memset(self, 0, sizeof(ThreeLoopPidFocV1_0));
    self->ConfigParam = Config_controller_PF018_E;
    self->Init = ThreeLoopPidFocV1_0_Init;

    self->param_control_mode = CONTROL_MODE_POSITION_CONTROL;
    self->param_control_algorithm = ControlAlgorithm_SeriesPidLeso;
    // self->param_pos_control_period_s = 14e-5; // 10k 5e-5;//20k 20e-5;//5k 100e-5;//1k
    self->param_en_all_control_switch = FALSE;

    /* spd feedforward */
    self->param_en_feedforward_speed = TRUE;
    self->param_feedforward_speed_limit = 999.0;

    /* idiq feedforward */
    self->param_en_feedforward_idiq = TRUE;
    self->param_feedforward_idiq_limit = 5.5;

    /* uduq feedforward */
    self->param_en_feedforward_uduq = TRUE;
    self->param_feedforward_uduq_limit = 999.0;
    self->param_speed_feedforward_mode = VoltageFeedforwardMode_SpdRef;

    /* pos loop */
    self->pos_loop_pid.Init = Pid_Init;
    self->pos_loop_pid.param_en = TRUE;
    self->pos_loop_pid.param_bypass = FALSE;
    // self->pos_loop_pid.param_T = self->param_pos_period;
    self->pos_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->pos_loop_pid.param_limit_ref = 999999.0F;
    self->pos_loop_pid.param_limit_ui = 0;
    self->pos_loop_pid.parma_limit_out = 3000 * RPM2RAD;
    self->pos_loop_pid.param_kp = 300.0;
    self->pos_loop_pid.param_ki = 0.0;
    self->pos_loop_pid.param_kd = 0.0;
    self->pos_loop_pid.param_kc = 0.0;
    self->pos_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->pos_loop_pid.ud_filter.param_en = FALSE;
    // self->pos_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->pos_loop_pid.ud_filter.param_fc = 1000;
    self->pos_loop_pid.fal.Init = FalLinear_Init;
    self->pos_loop_pid.fal.param_en = 0;
    self->pos_loop_pid.fal.param_a = 1.0;
    self->pos_loop_pid.fal.param_d = 1;
    self->pos_loop_pid.fal.param_zoom = 0.01;
    self->pos_loop_pid.fal.param_section_nums = 5;
    self->pos_loop_pid.fal.param_inteval_gain = 3;

    /* spd loop */
    self->spd_loop_pid.Init = Pid_Init;
    self->spd_loop_pid.param_en = TRUE;
    self->spd_loop_pid.param_bypass = FALSE;
    // self->spd_loop_pid.param_T = self->param_pos_period;
    self->spd_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->spd_loop_pid.param_limit_ref = 3000 * RPM2RAD;
    self->spd_loop_pid.param_limit_ui = 5.5;
    self->spd_loop_pid.parma_limit_out = 5.5;
    self->spd_loop_pid.param_kp = 0.15;
    self->spd_loop_pid.param_ki = 30.0;
    self->spd_loop_pid.param_kd = 0.0;
    self->spd_loop_pid.param_kc = 0.3;
    self->spd_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->spd_loop_pid.ud_filter.param_en = FALSE;
    // self->spd_loop_pid.ud_filter.param_Ts = self->param_pos_period;
    self->spd_loop_pid.ud_filter.param_fc = 1000;
    self->spd_loop_pid.fal.Init = FalLinear_Init;
    self->spd_loop_pid.fal.param_en = 1;
    self->spd_loop_pid.fal.param_a = 0.8;
    self->spd_loop_pid.fal.param_d = 1;
    self->spd_loop_pid.fal.param_zoom = 0.1;
    self->spd_loop_pid.fal.param_section_nums = 6;
    self->spd_loop_pid.fal.param_inteval_gain = 4;

    /* id loop */
    self->id_loop_pid.Init = Pid_Init;
    self->id_loop_pid.param_en = TRUE;
    self->id_loop_pid.param_bypass = FALSE;
    // self->id_loop_pid.param_T = self->param_cur_period;
    self->id_loop_pid.param_pid_mode = PID_MODE_KP_KI_INDEPENDENT;
    self->id_loop_pid.param_limit_ref = 5.5F;
    self->id_loop_pid.param_limit_ui = 1.0;
    self->id_loop_pid.parma_limit_out = 1.0;
    self->id_loop_pid.param_kp = 0.8;
    self->id_loop_pid.param_ki = 200.0;
    self->id_loop_pid.param_kd = 0.0;
    self->id_loop_pid.param_kc = 0.3;
    self->id_loop_pid.ud_filter.Init = Filter_FirstOrder_Init;
    self->id_loop_pid.ud_filter.param_en = FALSE;
    // self->id_loop_pid.ud_filter.param_Ts = self->param_cur_period;
    self->id_loop_pid.ud_filter.param_fc = 1000;
    self->id_loop_pid.fal.Init = FalLinear_Init;
    self->id_loop_pid.fal.param_en = 1;
    self->id_loop_pid.fal.param_a = 1.2;
    self->id_loop_pid.fal.param_d = 1;
    self->id_loop_pid.fal.param_zoom = 0.25;
    self->id_loop_pid.fal.param_section_nums = 5;
    self->id_loop_pid.fal.param_inteval_gain = 3;

    /* leso param */
    self->leso.Init = LESO_Init;
    self->leso.param_en = TRUE;
    // self->leso.param_h = self->param_pos_period;
    self->leso.param_b0k = 1;
    // self->leso.param_b0 = self->leso.param_b0k * 6000.0F; // * self->motor->param_Kt / self->motor->param_J;
    self->leso.param_z3k = 0;
    self->leso.param_wp = 4000;
    self->leso.param_ws = 4000;
    self->leso.param_wd = 400;
    self->leso.param_k0 = 1;
    self->leso.td.Init = TrackingDifferentiator_Init;
    self->leso.td.param_en = 0;
    self->leso.td.param_mode = TDMode_Fhan;
    // self->leso.td.param_h = self->param_pos_period;
    self->leso.td.param_h0_gain_h = 1.0F;
    self->leso.td.param_d_gain = 1.0;
    self->leso.td.param_dd_gain = 0.0;
    self->leso.td.fhan.Init = Fhan_Init;
    self->leso.td.fhan.param_en = 1;
    self->leso.td.fhan.param_f0 = 1000.0F;
    self->leso.fe.Init = FalLinear_Init;
    self->leso.fe.param_en = 0;
    self->leso.fe.param_a = 1.0;
    self->leso.fe.param_d = 1;
    self->leso.fe.param_zoom = 0.01;
    self->leso.fe.param_section_nums = 5;
    self->leso.fe.param_inteval_gain = 3;
    self->leso.fe1.Init = FalLinear_Init;
    self->leso.fe1.param_en = 0;
    self->leso.fe1.param_a = 1.0;
    self->leso.fe1.param_d = 1;
    self->leso.fe1.param_zoom = 0.001;
    self->leso.fe1.param_section_nums = 5;
    self->leso.fe1.param_inteval_gain = 3;

    /* field weakening control */
    self->fwc.Init = FieldWeakeningControl_Init;
    self->fwc.param_en = TRUE;
    self->fwc.param_speed_source_mode = FiledWeakeningControl_SpeedSource_SpdFdb;
    self->fwc.param_I_max = 5.5;
    // self->fwc.param_L = 1.01e-3;
    // self->fwc.param_phi_e = 0.11777F / 50;
    // self->fwc.param_pole_pair = 50;
    self->fwc.param_wm_base = 100;

    /* fdb selection */
    self->param_pos_acquire_method = PosAcquireMethod_LESO_z1; // PosAcquireMethod_DirectFromEncoder;//
    self->param_spd_acquire_method = SpdAcquireMethod_LESO_z2; // SpdAcquireMethod_DirectFromEncoder;//

    /* spd_fdb filter moving average */
    // self->spd_fdb_filter_moving_average.Init = Filter_MovingAverage_Init;
    // self->spd_fdb_filter_moving_average.param_en = FALSE;
    // self->spd_fdb_filter_moving_average.param_Ts = self->param_pos_period;
    // self->spd_fdb_filter_moving_average.param_fc = 1107.5;
    // self->spd_fdb_filter_moving_average.param_N = 5;

    /* spd_fdb filter FIR first-order */
    self->speed_filter.Init = Filter_FirstOrder_Init;
    self->speed_filter.param_en = FALSE;
    // self->speed_filter.param_Ts = self->param_pos_period;
    self->speed_filter.param_fc = 1000;

    /* iaib filter FIR first-order */
    self->ialpha_filter.Init = Filter_FirstOrder_Init;
    self->ialpha_filter.param_en = TRUE;
    // self->ialpha_filter.param_Ts = self->param_cur_period;
    self->ialpha_filter.param_fc = 3000;

    /* spd out notch filter settings */
    /* * notch filter 0 */
    self->spd_out_filter_notch[0].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[0].param_en = FALSE;
    // self->spd_out_filter_notch[0].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[0].param_f0 = 10000;
    self->spd_out_filter_notch[0].param_f_width = 30;
    self->spd_out_filter_notch[0].param_depth = 0.5;
    /* * notch filter 1 */
    self->spd_out_filter_notch[1].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[1].param_en = FALSE;
    // self->spd_out_filter_notch[1].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[1].param_f0 = 120;
    self->spd_out_filter_notch[1].param_f_width = 20;
    self->spd_out_filter_notch[1].param_depth = 0.5;
    /* * notch filter 2 */
    self->spd_out_filter_notch[2].Init = Filter_Notch_Init;
    self->spd_out_filter_notch[2].param_en = FALSE;
    // self->spd_out_filter_notch[2].param_Ts = self->param_pos_period;
    self->spd_out_filter_notch[2].param_f0 = 30;
    self->spd_out_filter_notch[2].param_f_width = 10;
    self->spd_out_filter_notch[2].param_depth = 0.5;

    /* spd out bifilter settings */
    self->spd_out_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->spd_out_filter_binary_second_order.param_en = TRUE;
    // self->spd_out_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->spd_out_filter_binary_second_order.param_fc = 10000;
    self->spd_out_filter_binary_second_order.param_depth = 1.0 / 3;
    self->spd_out_filter_binary_second_order.param_zeta_0N = 0.3;
    self->spd_out_filter_binary_second_order.param_zeta_0D = 0.5;

    /* z3 bifilter settings */
    self->z3_filter_binary_second_order.Init = Filter_BinarySecondOrder_Init;
    self->z3_filter_binary_second_order.param_en = TRUE;
    // self->z3_filter_binary_second_order.param_Ts = self->param_pos_period;
    self->z3_filter_binary_second_order.param_fc = 2000;
    self->z3_filter_binary_second_order.param_depth = 1.0 / 2;
    self->z3_filter_binary_second_order.param_zeta_0N = 0.2;
    self->z3_filter_binary_second_order.param_zeta_0D = 0.5;

    /* Tracking Differentiator */
    self->td.Init = TrackingDifferentiator_Init;
    self->td.param_en = TRUE;
    self->td.param_mode = TDMode_Fhan; // TDMode_Linear;//
    // self->td.param_h = self->param_pos_period;
    self->td.param_h0_gain_h = 20.0F;
    self->td.param_d_gain = 1.0;
    self->td.param_dd_gain = 0.0;
    self->td.fhan.Init = Fhan_Init;
    self->td.fhan.param_en = 1;
    self->td.fhan.param_f0 = 1000.0F; // 10;//

    /* motor ripple compensator */
    // self->motor_ripple_compensator.Init = MotorRippleCompensator_Init;
    // self->motor_ripple_compensator.en = FALSE;
    // self->motor_ripple_compensator.param_gain = 0.5;
    // self->motor_ripple_compensator.param_limit = 1.0;
    // float32 coeffs[NUM_OF_SIN_TERM][sizeof(SinCoeffs) / sizeof(float32)] = {
    //     {0.05, 1, 0},
    //     // {0.1,3,0},
    //     // {0.03,5,0},
    //     // {0.01,10,0},
    // };
    // for (size_t i = 0; i < NUM_OF_SIN_TERM; i++)
    // {
    //     memcpy(self->motor_ripple_compensator.sin_coeffs[i].all, coeffs[i], sizeof(SinCoeffs));
    // }

    /* Foc param */
    self->foc.Init = Foc_Init;
    self->foc.param_clark_mode = CLARK_MODE_EQUAL_AMPLITUDE_TRANSFORM;
}